// let array =[1,3,2,4];
// console.log(array.length);

/**
 * array.reverse()
 */
// let array = [1,3,2,4];
// console.log(array); //[ 1, 3, 2, 4 ]
// array.reverse();
// console.log(array); //[ 4, 2, 3, 1 ]
// let newArray = array.toReversed();
// console.log(array); //[ 4, 2, 3, 1 ]
// console.log(newArray); //[ 1, 3, 2, 4 ]

/**
 * array.sort()
 */
// let arrayA = [1,9,200,100];
// console.log(arrayA.sort()); // [ 1, 100, 200, 9 ]
// let arrayB = ['Cendy','cendy','Amy','Jome'];
// console.log(arrayB.sort()); // [ 'Amy', 'Cendy', 'Jome', 'cendy' ]
// let arrayC = ['我','你','他'];
// console.log(arrayC[0].charCodeAt(0)); // 25105
// console.log(arrayC[1].charCodeAt(0)); // 20320
// console.log(arrayC[2].charCodeAt(0)); // 20182
// console.log(arrayC.sort()); // [ '他', '你', '我' ]
// let arrayD = [5,1,99,11,2];
//     /**
//      * a>b,则a排在b后面 
//      * a<b,则a排在b前面 
//      */
//     function compareNumbers1(a, b) {
//         return a - b;
//     }
//     /**
//      * a>b,则a排在b前面 
//      * a<b,则a排在b后面 
//      */
//     function compareNumbers2(a, b) {
//         return b - a;
//     }
//     console.log(arrayD.sort(compareNumbers1)); // [ 1, 2, 5, 11, 99 ]
//     console.log(arrayD.sort(compareNumbers2)); // [ 1, 2, 5, 11, 99 ]

/**
 * array.at()
 */
// let arrayA = [2,23,1,90,100];
// console.log(arrayA.at(1)); // 23
// console.log(arrayA.at(1.6)); // 23
// console.log(arrayA.at(1.4)); // 23
// console.log(arrayA.at(-1)); // 100
// console.log(arrayA.at(-1.1)); // 100
// console.log(arrayA.at(5)); // undefined
// /**
//  * 非数组,需要有length属性，且length可大不可小
//  */
// let object = {
//     length:2,
//     '0':'ok',
//     '1':'okk'
// }
// console.log(Array.prototype.at.call(object,1)); // okk
/**
 * array.fill()
 */
// console.log([1,2,3].fill()); // [ undefined, undefined, undefined ]
// console.log([1,2,3].fill('a')); // [ 'a', 'a', 'a' ]
// console.log([1,2,3].fill('a',1)); // [ 1, 'a', 'a' ]
// console.log([1,2,3].fill('a',0,1)); // [ 'a', 2, 3 ]

// // 小数向下取整，[ 'a', 2, 3 ]
// console.log([1,2,3].fill('a',0.5,1));
// console.log([1,2,3].fill('a',0.4,1));

// // [ 1, 2, 'a' ]
// console.log([1,2,3].fill('a',-1));
// console.log([1,2,3].fill('a',-1,3));
// console.log([1,2,3].fill('a',-1.5,3));
// console.log([1,2,3].fill('a',2,3));

// console.log([1,2,3].fill('a',-4,5)); // [ 'a', 'a', 'a' ]
// console.log([1,2,3].fill('a',0,-1)); // [ 'a', 'a', 3 ]
// // 会生成一个相同对象引用的数组
// const arr1 = Array(3).fill({});
// arr1[0].hi = "hi";
// console.log(arr1) // [ { hi: 'hi' }, { hi: 'hi' }, { hi: 'hi' } ]

// const arr2 = [...Array(3)];
// arr2[0] = {hi:"hi"};
// console.log(arr2) // [ { hi: 'hi' }, undefined, undefined ]
// // 非数组，基本原理同上

/**
 * array.from()
 */
// const arrayA = [1,2,3,4];
// console.log(arrayA.prototype)
/**
 * array.join()
 */
// const arrayA = [1,2,3,'ok'];
// // 默认是逗号隔开
// console.log(arrayA.join()); // 1,2,3,ok
// // 指定字符隔开
// console.log(arrayA.join('')); // 123ok
// console.log(arrayA.join('!')); // 1!2!3!ok
// // 稀疏数组中，空槽会被视为undefind
// console.log([1, , 3].join()); // 1,,3
// console.log([1, undefined , 3].join()); // 1,,3
/**
 * array.toString()
 */
// console.log(['a',1,2,'ok'].toString()); // a,1,2,ok
/**
//  * array.pop()
//  */
// const arrayA = ['a',1,'ok'];
// const poped = arrayA.pop();
// console.log(arrayA,poped); // [ 'a', 1 ] ok
// // 类数组对象、非数组对象同理。mdn示例：
// const plainObj = {};
// // 没有 length 属性，所以长度为 0
// Array.prototype.pop.call(plainObj);
// console.log(plainObj); // { length: 0 }
// /**
//  * 迭代器示例，接受一个数组
//  * @param {Array} array 
//  * @returns 返回value和done组成的对象
//  */
// function makeIterator(array){
//     let nextIndex = 0;
//     return {
//         next:function(){
//             // let result;
//             // if(nextIndex<array.length){
//             //     result = {value:array[nextIndex],done:false};
//             //     nextIndex++;
//             // }else{
//             //    result = {done:true};
//             // }
//             // return result;
//             //这是简写
//             return nextIndex<array.length?
//                 {value:array[nextIndex++],done:false}:{done:true};
//         }
//     }
// }
// let it = makeIterator([1,2,3])
// console.log(it.next()); // { value: 1, done: false }
// console.log(it.next()); // { value: 2, done: false }
// console.log(it.next()); // { value: 3, done: false }
// console.log(it.next()); // { done: true }

// let it2 = makeIterator(['a','b','c']);
// let result = it2.next();
// while(!result.done){
//     console.log(result.value);
//     result = it2.next();
// }
// let it3 = makeIterator(['a','b','c']);
// let result3;
// while(!(result3=it3.next()).done){
//     console.log(result3.value);
// }
// /**
//  * array.shift()
//  */
//  const array = [1, 2, 3];
//  const first = array.shift();
//  console.log(first,array); // 1 [ 2, 3 ]
// /**
//  * array.slice()
//  */
// let array = [1,2,3,4];
// // [ 1, 2, 3, 4 ]
// console.log(array);
// console.log(array.slice());
// console.log(array.slice(0, array.length));
// console.log(array.slice(-array.length));
// // 正负关系参照Array.fill()...

// //虽然不会改变原数组，但是是浅拷贝，修改新数组的对象值会影响原数组。
// let obj = {
//     ok:'yes'
// }
// let arrayA = [obj,1,2];
// console.log(arrayA); // [ { ok: 'yes' }, 1, 2 ]
// let arrayB = arrayA.slice();
// arrayB[0].ok = 'no'; // [ { ok: 'no' }, 1, 2 ]
// console.log(arrayA);
// console.log(obj); // [ { ok: 'no' } ]
// /**
//  * array.copyWithin()
//  */
// const arrayA = [1,2,3,4];
// const arrayCopyA = arrayA.copyWithin(1,0,4);
// // [ 1, 1, 2, 3 ] 原数组也发生了改变
// console.log(arrayA,arrayCopyA);

// const arrayB = [1,2,3,4];
// // [1,2,3,4] 默认值
// console.log(arrayB.copyWithin(0,0,4));
// console.log(arrayB.copyWithin(0));
// console.log(arrayB.copyWithin());

// const arrayC = [1,2,3,4];
// // 小数值、负数值
// console.log(arrayC.copyWithin(0.5));// [ 1, 2, 3, 4 ]
// console.log(arrayC.copyWithin(0.4));// [ 1, 2, 3, 4 ]
// console.log(arrayC.copyWithin(-0.5));// [ 1, 2, 3, 4 ]
// console.log(arrayC.copyWithin(-1.2));// [ 1, 2, 3, 1 ]

// /**
//  * array.push()
//  */
// // 参数可以任意多
// const arrayA = [1,2];
// const len = arrayA.push('a','b');
// console.log(len,arrayA); // 4 [ 1, 2, 'a', 'b' ]
// // 合并两个数组，解构，追加
// const arrayB = [1,2]
// const totalB = arrayB.push(...[3,4]);
// console.log(totalB,arrayB); // 4 [ 1, 2, 3, 4 ]

// /**
//  * array.unshift()
//  */
// // 参数可以任意多
// const arrayA = [1,2];
// const len = arrayA.unshift('a','b');
// console.log(len,arrayA); // 4 [ 1, 2, 'a', 'b' ]
// // 合并两个数组，解构，追加
// const arrayB = [1,2]
// const totalB = arrayB.unshift(...[3,4]);
// console.log(totalB,arrayB); // 4 [ 1, 2, 3, 4 ]

// /**
//  * array.concat()
//  */
// // 常规用法1
// const arrayA = [1,2];
// const arrayB = [3,4];
// // 解构与否都会使两数组合并 [ 1, 2, 3, 4 ]
// console.log(arrayA.concat('x',arrayB));
// console.log(arrayA.concat('x',...arrayB));
// // 先后顺序取决于调用先后，以及调用者 [ 3, 4, 1, 2 ]
// console.log(arrayB.concat(arrayA));
// // 常规用法2
// const obj = {
//     ok: 'yes'
// }
// const array = [1,2,obj];
// const arrayConcated =array.concat();
// // concat浅拷贝一份原数组
// console.log(arrayConcated); // [ 1, 2, { ok: 'yes' } ]
// // 修改浅拷贝的值,会改变原数组
// arrayConcated[2].ok = 'no';
// console.log(array); // [ 1, 2, { ok: 'no' } ]
// console.log(obj); // { ok: 'no' }
// // 区别于其他，对于类数组对象，只有Symbol.isConcatSpreadable]为true的时候才会合并
// const obj1 = { 0: 1, 1: 2, length: 2 };
// const obj2 = { 0: 1, 1: 2, length: 2, [Symbol.isConcatSpreadable]: true };
// console.log([0].concat(obj1, obj2));
// // [ 0, { '0': 1, '1': 2, length: 2 }, 1, 2 ]
// /**
//  * array.some()
//  */
// const array = [1,2,3,5];
// const fn = (element,index) => {
//     console.log(element,index); // 1 0,2 1,3 2,5 3
//     return element % (index + 1) !== 0;
// }
// console.log(array.some(fn)); // true
// console.log([1,,2].some((e) => {
//     return typeof e !== 'number'
// })); // false
// /**
//  * array.splice()
//  */
// const arrayA = [1,2,3,4];
// // 如果不传参数，不会改变原数组
// console.log(arrayA.splice()); // []
// console.log(arrayA); // [ 1, 2, 3, 4 ]
// // undefined 会转换成0
// const arrayB = [1,2,3,4];
// const arrayC = [1,2,3,4];
// console.log(arrayB.splice(undefined)); // [ 1, 2, 3, 4 ]
// console.log(arrayB); // []
// console.log(arrayC.splice(0)); // [ 1, 2, 3, 4 ]
// console.log(arrayC); // []
// // 由以上可得，第二个参数deleteCount如果不填则为全部start后面的
// const arrayD = [1,2,3,4];
// // 从索引为1的元素开始（包括），删除两个元素
// console.log(arrayD.splice(1,2)); // [ 2, 3 ]
// console.log(arrayD); // [ 1, 4 ]
// // 关于start的正负号原理同其他数组方法
// // 如果指定了新的参数，则此方法在start后插入item
// const arrayE = [1,2,3];
// // 由以下可见splice方法的返回值只有删除的情况，未删除为[]
// console.log(arrayE.splice(1,0,'item1')); // []
// console.log(arrayE); // [ 1, 'item1', 2, 3 ]
// // deleteCount先执行完再添加，可添加多个
// const arrayF = [1,2,3];
// console.log(arrayF.splice(1,2,'item1','item2')); // [ 2, 3 ]
// console.log(arrayF); // [ 1, 'item1', 'item2' ]
// // 不改变稀疏数组性质
// // 拓展方法toSplice() 限浏览器环境
// const arrayG = [1,2,3];
// console.log(arrayG.toSpliced(1,1)); // [ 1, 3 ]
// console.log(arrayG); // [ 1, 2, 3 ]
// /**
//  * array.flat()
//  */
// const arrayA = [1,2,3,[4,5]];
// // 不填depth，默认为1 --- [ 1, 2, 3, 4, 5 ]
// console.log(arrayA.flat());
// console.log([1,[[[2,3]]]].flat(1)); // [ 1, [ [ 2, 3 ] ] ]
// console.log([1,[[[2,3]]]].flat(2)); // [ 1, [ 2, 3 ] ]
// console.log([1,[[[2,3]]]].flat(3)); // [ 1, 2, 3 ]
// // 如果不存在这么深的结构则递归最深的结构---[ 1, 2, 3, 4, 5 ]
// console.log(arrayA.flat(2));
// const arrayB = [1,[[[2,[[[3,[[4]]]]]]]]];
// // 如果数组结构混乱或者难以辨别或者未知，可以使用如下：
// console.log(arrayB.flat(Infinity)); // [ 1, 2, 3, 4 ]
// // 稀疏数组的空槽会被删除
// const arrayC = [1,,2,[3,,4]];
// console.log(arrayC.flat(Infinity)); // [ 1, 2, 3, 4 ]
// // 对于类数组对象，如果元素值是数组会被展平，嵌套对象不会被展平
// /**
//  * array.lastIndexOf()
//  */
// // 没有找到则返回 --- -1
// console.log([1,2,1,3].lastIndexOf());
// console.log([1,2,1,3].lastIndexOf(4));
// // 找到了则返回对应的值最后出现的索引 --- 2
// console.log([1,2,1,3].lastIndexOf(1));
// // 可以指定查找结束位置
// console.log([1,2,1,3].lastIndexOf(1,0)); // 0
// console.log([1,2,1,3].lastIndexOf(1,3)); // 2
// // 负数可参与
// console.log([1,2,1,3].lastIndexOf(1,-4)); // 0
// // 小于负的数组长度，不存在
// console.log([1,2,1,3].lastIndexOf(1,-5)); // -1
// // 会跳过稀疏数组的空槽
// console.log([1,,,2,1,3].lastIndexOf(undefined)); // -1
// // MDN 示例改造，查找一个数组某个元素出现的所有索引
// /**
//  * 查找一个数组某个元素出现的所有索引
//  * @param {Array} array 
//  * @param {*} element 
//  * @returns 索引数组
//  */
// function findAllIndex(array,element){
//     const indices = [];
//     let idx = array.lastIndexOf(element);
//     while (idx !== -1) {
//         indices.unshift(idx);
//         idx = idx > 0 ? array.lastIndexOf(element, idx - 1) : -1;
//     }
//     return indices;
// }
// console.log(findAllIndex([1,2,1,1,3],1)); // [ 0, 2, 3 ]
// /**
//  * Array.of()
//  */
// console.log(Array.of(1,2,3)); // [ 1, 2, 3 ]
// console.log(Array.of(undefined)); // [ undefined ]
// // 与Array构造方法的区别在于对特殊处理上
// console.log(Array(7)) // [ <7 empty items> ]
// /**
//  * array.every()
//  */
// // 指定函数，参数和返回与some方法相似
// const isString = (element,index,array) => typeof element === 'string';
// const arrayA = [1,2,'3'];
// console.log(arrayA.every(isString))
// console.log(arrayA.every(isString))

// /**
//  * 把数组按出现次数转化成对象
//  * @param {*} accumulator 
//  * @param {*} currentValue 
//  * @returns 单次reduce迭代的值
//  */
// const callbackFn = (accumulator, currentValue) => {
//     if (accumulator[currentValue]) {
//         accumulator[currentValue]++;
//     } else {
//         accumulator[currentValue] = 1;
//     }
//     return accumulator;
// };
// const objA = [2, 2,, 4, 6].reduce(callbackFn, {});
// const objB = [1, 2, 2, 3, 4, 5, 6, 7, 8].reduce(callbackFn, {});
// /**
//  * 判断a对象是否包含b对象
//  * @param {Object} a 
//  * @param {Object} b 
//  * @returns true or false
//  */
// const isSon = (a, b) => {
//     return Object.entries(b).every(([key, value]) => a[key] === value)
// };
// console.log(isSon(objA, objB) || isSon(objB, objA));

// function isSon(arrayA,arrayB){
//     return arrayA.every(element=>arrayB.includes(element));
// }
// console.log(isSon([1,2],[1,2,3,4]));
// /**
//  * array.values()
//  */
// const array = [1,2,3];
// const iterator = array.values();
// console.log(iterator.next()); // { value: 1, done: false }
// console.log(iterator.next()); // { value: 2, done: false }
// console.log(iterator.next()); // { value: 3, done: false }
// console.log(iterator.next()); // { value: undefind, done: true }
// // array.values()是[@@iterator]()方法的默认实现
// const arrayB = [1, 2, 3];
// const iteratorB = arrayB[Symbol.iterator]();
// console.log(iteratorB.next()); // { value: 1, done: false }
// console.log(iteratorB.next()); // { value: 2, done: false }
// console.log(iteratorB.next()); // { value: 3, done: false }
// console.log(iteratorB.next()); // { value: undefind, done: true }
// console.log([1,2,3][Symbol.iterator])
// /**
//  * Array.from()
//  */
// // 把字符串转成数组
//  console.log(Array.from('hi')); // [ 'h', 'i' ]
//  // [ '0:1', '1:2', '2:3' ]
// //  浅拷贝 --- [ 1, { name: 'ok' } ]
//  console.log(Array.from([1, 2, 3], (element,index) => index + ':' + element));
//  const obj = {
//      name: '之豪'
//  }
//  const newArray = Array.from([1,obj]);
//  obj.name = 'ok';
//  console.log(newArray);
//  支持从可迭代对象（例如 Map 和 Set 对象）或类数组对象（带有 length 属性和索引元素的对象）中构建数组
/**
 * array.every()
 */
